
#include "MapManager.h"
#include "GameString.h"
#include "msgDefine.h"
#include "CreatureManager.h"




MapManager* gMapManager = F_NULL;

RECV_MSG_SYN_TEAM gMsgSynTeam;
RECV_MSG_JOIN_TEAM gMsgJoinTeam;
RECV_MSG_LEAVE_TEAM gMsgLeaveTeam;

MapManager::MapManager()
{
	gMapManager = this;
}

MapManager::~MapManager()
{

}



fvoid		MapManager::LoadMapWarp( const fbyte* path )
{
    ptree pt;
    
    read_xml( path , pt , boost::property_tree::xml_parser::trim_whitespace );
    
    FLOG4( "xml loading. %s" , path );
    
    pt = pt.get_child( "root" );
    
    ptree::assoc_iterator iter = pt.ordered_begin();
    
    for (  ; iter != pt.not_found() ; ++iter )
    {
        ptree n = iter->second;
        
        fint32 id = n.get< fint32 >( "<xmlattr>.m" );
        fint32 x = n.get< fint32 >( "<xmlattr>.x" );
        fint32 y = n.get< fint32 >( "<xmlattr>.y" );
        fint32 link1 = n.get< fint32 >( "<xmlattr>.ml" );
        fint32 linkX = n.get< fint32 >( "<xmlattr>.xl" );
        fint32 linkY = n.get< fint32 >( "<xmlattr>.yl" );
        
        MapScene* scene = GetScene( id );
        if ( !scene )
        {
            FLOG4( "link error scene=%d" , id );
            continue;
        }
        if ( !scene->CheckGrid( x , y ) )
        {
            FLOG4( "link error scene=%d x=%d y=%d" , id , x , y );
            continue;
        }
        
        MapGrid* grid = scene->GetGrid( MapGridID( x , y ) );
        
        MapGridLink link;
        link.mMapID = link1;
        link.mGridID.x = linkX;
        link.mGridID.y = linkY;
        
        grid->mLinks.push_back( link );
    }
    
    FLOG4( "xml loaded. %s" , path );
}


fvoid		MapManager::LoadMap()
{
	// load data
    
    fileVector vector;
    
    fileTools::getSubFiles( "map/" , vector );

    
	for ( fint32 i = 0 ; i < vector.size() ; ++i )
    {
        fbyte buffer[ 4 ] = {};
        
        fint32 find = (fint32)vector[ i ].find( "." );
        string fileName = vector[ i ].substr( 0 , find );
        find = (fint32)fileName.find_last_of( '/' );
        if ( find <= 0 )
        {
            find = (fint32)fileName.find_last_of( '\\' );
        }
        
        fileName = fileName.substr( find + 1 );
        
        if ( fileName.empty() )
        {
            continue;
        }
        
        FILE* file = fopen( vector[ i ].c_str() , "r" );
        
        fread( buffer , 1 , 2 , file );
        fint32 maxX = *( (fint32*)buffer );

        fread( buffer , 1 , 2 , file );
        fint32 maxY = *( (fint32*)buffer );
        
        fint32 id = atoi( fileName.c_str() );
        
        MapScene* scene = new MapScene();
        scene->SetID( id );
        scene->Init( maxX , maxY );
        
        mScenesMap[ id ] = scene;
        mScenes.push_back( scene );
        
        fclose( file );
    }

    
    FLOG4( "map scenes count=%d" , mScenes.size() );
}


fvoid		MapManager::LoadEnemyCount( const fbyte* path )
{
    ptree pt;
    ptree root;
    
    read_xml( path , pt , boost::property_tree::xml_parser::trim_whitespace );
    
    FLOG4( "xml loading. %s" , path );
    
    root = pt.get_child( "root" );
    
    ptree::assoc_iterator iter = root.ordered_begin();
    
    for (  ; iter != root.not_found() ; ++iter )
    {
        ptree n = iter->second;
        
        GameEnemyCount count;
        
        count.intValue[ GECIV_ID ] = n.get< fint32 >( "<xmlattr>.id" );
        count.intValue[ GECIV_MAPID ] = n.get< fint32 >( "<xmlattr>.mapID" );
        
        count.intValue[ GECIV_X1 ] = n.get< fint32 >( "<xmlattr>.x1" );
        count.intValue[ GECIV_Y1 ] = n.get< fint32 >( "<xmlattr>.y1" );
        count.intValue[ GECIV_X2 ] = n.get< fint32 >( "<xmlattr>.x2" );
        count.intValue[ GECIV_Y2 ] = n.get< fint32 >( "<xmlattr>.y2" );
        
        count.intValue[ GECIV_MIN ] = n.get< fint32 >( "<xmlattr>.min" );
        count.intValue[ GECIV_MAX ] = n.get< fint32 >( "<xmlattr>.max" );
        count.intValue[ GECIV_NUM ] = n.get< fint32 >( "<xmlattr>.num" );
        count.intValue[ GECIV_UNKNOW ] = n.get< fint32 >( "<xmlattr>.unkown" );
        
        count.intValue[ GECIV_GROUP0 ] = n.get< fint32 >( "<xmlattr>.group0" );
        count.intValue[ GECIV_GROUP1 ] = n.get< fint32 >( "<xmlattr>.group1" );
        count.intValue[ GECIV_GROUP2 ] = n.get< fint32 >( "<xmlattr>.group2" );
        count.intValue[ GECIV_GROUP3 ] = n.get< fint32 >( "<xmlattr>.group3" );
        count.intValue[ GECIV_GROUP4 ] = n.get< fint32 >( "<xmlattr>.group4" );
        count.intValue[ GECIV_GROUP5 ] = n.get< fint32 >( "<xmlattr>.group5" );
        count.intValue[ GECIV_GROUP6 ] = n.get< fint32 >( "<xmlattr>.group6" );
        count.intValue[ GECIV_GROUP7 ] = n.get< fint32 >( "<xmlattr>.group7" );
        count.intValue[ GECIV_GROUP8 ] = n.get< fint32 >( "<xmlattr>.group8" );
        count.intValue[ GECIV_GROUP9 ] = n.get< fint32 >( "<xmlattr>.group9" );
        
        count.intValue[ GECIV_GROUPPRO0 ] = n.get< fint32 >( "<xmlattr>.groupPro0" );
        count.intValue[ GECIV_GROUPPRO1 ] = n.get< fint32 >( "<xmlattr>.groupPro1" );
        count.intValue[ GECIV_GROUPPRO2 ] = n.get< fint32 >( "<xmlattr>.groupPro2" );
        count.intValue[ GECIV_GROUPPRO3 ] = n.get< fint32 >( "<xmlattr>.groupPro3" );
        count.intValue[ GECIV_GROUPPRO4 ] = n.get< fint32 >( "<xmlattr>.groupPro4" );
        count.intValue[ GECIV_GROUPPRO5 ] = n.get< fint32 >( "<xmlattr>.groupPro5" );
        count.intValue[ GECIV_GROUPPRO6 ] = n.get< fint32 >( "<xmlattr>.groupPro6" );
        count.intValue[ GECIV_GROUPPRO7 ] = n.get< fint32 >( "<xmlattr>.groupPro7" );
        count.intValue[ GECIV_GROUPPRO8 ] = n.get< fint32 >( "<xmlattr>.groupPro8" );
        count.intValue[ GECIV_GROUPPRO9 ] = n.get< fint32 >( "<xmlattr>.groupPro9" );
        
        
        mGameEnemyCountMap[ count.intValue[ GEIV_ID ] ] = count;
        
        
        MapSceneMapIter iter = mScenesMap.find( count.intValue[ GECIV_MAPID ] );
        
        if ( iter != mScenesMap.end() )
        {
            for ( fint32 i = count.intValue[ GECIV_Y1 ] ; i < count.intValue[ GECIV_Y2 ] ; ++i )
            {
                for ( fint32 j = count.intValue[ GECIV_X1] ; j < count.intValue[ GECIV_X2 ] ; ++j )
                {
                    if ( count.intValue[ GECIV_MAX ] )
                    {
                        MapGrid* grid = iter->second->GetGrid( MapGridID( j , i ) );
                        grid->mEnemyRand = MathBase::GetRandomInt( count.intValue[ GECIV_MIN ] , count.intValue[ GECIV_MAX ] );
                        grid->mECID = count.intValue[ GECIV_ID ];
                    }
                    
                }
            }
            
        }
        
    }
    
    FLOG4( "xml loaded. %s" , path );
}


MapScene*	MapManager::GetScene( fint32 id )
{
	MapSceneMapIter iter = mScenesMap.find( id );

	if ( iter != mScenesMap.end() )
	{
		return iter->second;
	}

	return F_NULL;
}


fvoid		MapManager::Update( freal32 delay )
{
	static freal32 time = 0.0f;
	time += delay;

	if ( time < 0.04f )
		return;

	fint32 count = (fint32)mScenes.size();

	for ( fint32 i = 0 ; i < count ; ++i )
	{
		mScenes[i]->Update( time );
	}

	UpdateNpc( time );
	ChangeMap( time );

	time = 0.0f;
}

fvoid		MapManager::EnterScene( GamePlayer* player )
{
	CreatureMoveData& data = player->GetMoveData();
	
	MapScene* scene = GetScene( data.Pos.MapID );

	if ( scene )
	{
		scene->AddPlayer( player );
	}

}

fvoid		MapManager::ExitScene( GamePlayer* player )
{
	CreatureMoveData& data = player->GetMoveData();

	MapScene* scene = GetScene( data.Pos.MapID );

	if ( scene )
	{
		scene->RemovePlayer( player );
	}
	
	mWaitPlayers.remove( player );
}

fvoid		MapManager::JoinTeam( GamePlayer* leader , GamePlayer* player )
{
	GameTeam* pteam = player->GetTeam();

	if ( pteam )
	{

	}
	else
	{
		GameTeam* team = leader->GetTeam();
		fbool b = F_FALSE;

		if ( team )
		{
			b = team->Join( player );
		}
		else
		{
			team = gCreatureManager->CreatTeam();
			team->Init( leader );
			b = team->Join( player );
		}

		if ( b )
		{
			MapScene* scene = gMapManager->GetScene( player->GetMoveData().Pos.MapID );

			CreatureData& data = player->GetData();
			CreatureFightData& fightData = player->GetFightData();

			gMsgJoinTeam.GUID = leader->GetGUID();
			gMsgJoinTeam.Player.GUID = data.ID;
			gMsgJoinTeam.Player.HP = fightData.Base.HP;
			gMsgJoinTeam.Player.MAXHP = fightData.Base.MAXHP;
			gMsgJoinTeam.Player.MP = fightData.Base.MP;
			gMsgJoinTeam.Player.MAXMP = fightData.Base.MAXMP;

			scene->SendMsgToAll( &gMsgJoinTeam , player->GetGUID() );

			gMsgSynTeam.Count = 0;
			
			for ( fint32 i = 0 ; i < team->mMemberCount - 1; ++i )
			{
				CreatureData& data = team->mMembers[i]->GetData();
				CreatureFightData& fightData = team->mMembers[i]->GetFightData();

				gMsgSynTeam.Player[ gMsgSynTeam.Count ].GUID = data.ID;
				gMsgSynTeam.Player[ gMsgSynTeam.Count ].HP = fightData.Base.HP;
				gMsgSynTeam.Player[ gMsgSynTeam.Count ].MAXHP = fightData.Base.MAXHP;
				gMsgSynTeam.Player[ gMsgSynTeam.Count ].MP = fightData.Base.MP;
				gMsgSynTeam.Player[ gMsgSynTeam.Count ].MAXMP = fightData.Base.MAXMP;

				gMsgSynTeam.Count++;
			}

			gMsgSynTeam.size = 8 + sizeof( MsgPlayer ) * gMsgSynTeam.Count;
			player->PackMsg( &gMsgSynTeam );
			player->SendMsg();
		}


	}
}

fvoid		MapManager::LeaveTeam( GamePlayer* player )
{
	GameTeam* team = player->GetTeam();

	if ( team )
	{
		fbool b = team->Leave( player );

		if ( b )
		{
			MapScene* scene = gMapManager->GetScene( player->GetMoveData().Pos.MapID );

			gMsgLeaveTeam.GUID = player->GetGUID();

			scene->SendMsgToAll( &gMsgLeaveTeam );
		}
	}


}

fvoid		MapManager::AddWaitPlayer( GamePlayer* player )
{
	mWaitPlayers.push_back( player );
}

fvoid		MapManager::AddWaitNpc( GameNpc* npc )
{
	mWaitNpc.push_back( npc );
}

fvoid		MapManager::UpdateNpc( freal32 delay )
{
	if ( mWaitNpc.empty() )
	{
		return;
	}

	GameNpcListIter iterEnd = mWaitNpc.end();

	for ( GameNpcListIter iter = mWaitNpc.begin() ; iter != iterEnd ; )
	{
//		MapScene* scene = GetScene( (*iter)->mMoveData.Pos.MapID );
//		
//		(*iter)->mDelay += delay;
//
//		if ( (*iter)->mDelay > (*iter)->mCreateData.Time )
//		{
//			(*iter)->mDelay = 0.0f;
//			(*iter)->SetFall( F_FALSE );
//			scene->MoveNpc( (*iter) );
//			
//			iter = mWaitNpc.erase( iter );
//		}
//		else
//		{
//			++iter;
//		}
	}

}

fvoid		MapManager::ChangeMap( freal32 delay )
{
	if ( mWaitPlayers.empty() )
	{
		return;
	}
    
    static freal32 time = 0.0f;
    time += delay;
    if ( time < 0.7f )
    {
        return;
    }

    time = 0.0f;

	GamePlayerListIter iterEnd = mWaitPlayers.end();

	for ( GamePlayerListIter iter = mWaitPlayers.begin() ; iter != iterEnd ; ++iter )
	{
		MapScene* scene = GetScene( (*iter)->mMoveData.Pos.MapID );
		MapGrid* grid = scene->GetGrid( (*iter)->mMoveData.Pos.Grid );

		scene->RemovePlayer( (*iter) );

		(*iter)->SetState( GameCreature::GCSSTAND );
        fint32 rand1 = RAND() % grid->mLinks.size();
		(*iter)->mMoveData.Pos.MapID = grid->mLinks[ rand1 ].mMapID;
		(*iter)->mMoveData.Pos.Grid = grid->mLinks[ rand1 ].mGridID;

		EnterScene( (*iter) );
		(*iter)->SendMsg();
		(*iter)->SendMsgToTeam();
	}

	mWaitPlayers.clear();
}


fvoid		MapManager::WarpScene( GamePlayer* player , MapPos& pos )
{
	MapScene* scene = GetScene( player->mMoveData.Pos.MapID );
	MapGrid* grid = scene->GetGrid( player->mMoveData.Pos.Grid );

	scene->RemovePlayer( player );

	player->SetState( GameCreature::GCSSTAND );
	player->mMoveData.Pos = pos;

	EnterScene( player );
	player->SendMsg();
	player->SendMsgToTeam();
}


GameEnemyCount*		MapManager::GetGameEnemyCount( fint32 id )
{
	GameEnemyCountMapIter iter = mGameEnemyCountMap.find( id );

	return &(iter->second);
}
